#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

#define SIZE 1024
#define ARGC 64

int EXIT = 0;

void inputCommand(char* out)
{
  printf("[%s@%s %s]$ ", getenv("USER"), getenv("HOSTNAME"), getenv("PWD"));
  fgets(out, SIZE, stdin);
  out[strlen(out) - 1] = '\0';
}

void getArgv(char* command, char** out)
{
  int i = 0;
  out[i++] = strtok(command, " ");
  while (out[i++] = strtok(NULL, " "));
}

int buildCommand(char** argv)
{
  int ret = 0;
  if (strcmp(argv[0], "cd") == 0)
  {
    ret = 1;
    char* path = argv[1];
    char put[SIZE];
    char absolutePath[SIZE];

    if (path == NULL)
      path = getenv("HOME");
    
    chdir(path);
    getcwd(absolutePath, SIZE);
    
    snprintf(put, SIZE, "%s%s", "PWD=", absolutePath);
    putenv(put);
  }
  else if (strcmp(argv[0], "export") == 0)
  {
    ret = 1;
    char env[SIZE];
    if (argv[1])
    {
      strcpy(env, argv[1]);
      putenv(env);
    }
  }
  else if (strcmp(argv[0], "echo") == 0)
  {
    ret = 1;
    if (argv[1] == NULL)
      printf("\n");
    else
    {  
      if (argv[1][0] == '$')
      {
        if (argv[1][1] == '?')
        {
          printf("%d\n", EXIT);
          EXIT = 0;
        }
        else 
        {
          char* env = getenv(argv[1] + 1);
          if (env == NULL)
            printf("\n");
          else 
            printf("%s\n", env);
        }
      } 
      else 
        printf("%s\n", argv[1]);                    
     }
  }


  return ret;
}

void execute(char** argv)
{
    pid_t pid = fork();
    if (pid == 0)
    {
      execvp(argv[0], argv);
      exit(1);
    }

    int status;
    pid_t rid = waitpid(pid, &status, 0);
    EXIT = WEXITSTATUS(status);
}

int main()
{
  while(1)
  {
    //获取命令行参数
    char command[SIZE] = {0};
    inputCommand(command);
    if (strlen(command) == 0)
      continue;

    //将命令行拆分成多个字符串
    char* argv[ARGC];
    getArgv(command, argv);
    
    
    //处理内建命令
    int ret = buildCommand(argv);

    //执行命令
    if (!ret)
      execute(argv);
  }

  return 0;
}
